iOS UISwipeGestureRecognizer: Two Ways in Swift

I’ve been building a small sample iOS app and in learning how to implement UISwipeGestureRecognizer, found two different approaches. None of the resources I found online were overly explicit in both approaches, so documenting here…mostly for my own future reference.

Option 1: Storyboard

Xcode makes it easy to add a gesture recognizer to your app interface. Simply drag the appropriate gesture recognizer from the palette onto Storyboard, being sure to select the UI element that you would like to listen for the gesture. In my case, the entire view of my ViewController:

Screen Shot 2015-11-18 at 2.34.27 PM

Next, select the gesture recognizer and Ctrl+Drag to your ViewController class. Select the settings as shown below in the pop-up. You can now implement the response to your gesture.

Screen Shot 2015-11-18 at 2.36.38 PM

The Storyboard inspector also allows you to select swipe direction, etc. with the gesture recognizer selected.

Option 2: Code

Adding a gesture recognizer (in this case, a swipe gesture recognizer) requires just a few lines of code in your ViewController, typically in your viewDidLoad method.


let swipeRight:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "doSomething:")
swipeRight.direction = .Right
self.view.addGestureRecognizer(swipeRight)

The only item left is to implement the handler for gesture, which is mostly identical to Option 1:


func doSomething(gestureRecognizer:UIGestureRecognizer) {
print("doSomething called")
}

My preference is Option 1. Although the implementation is spread across two files, keeping all view-related bits in the Storyboard feels cleaner, but either approach will work.


“Banners” = Bad in Ad Blocker World

Just ran into a rather aggravating issue…

In building a site meant to preview mobile ads, I used the term “banners” in the URL to point to image previews then spent 2+ hours tracking down why it worked in my development environment but not in production.

Luckily a colleague pointed out my ad blocker, which seems to have a broad match on the word “banner”…block all. Changing the name in the path fixed the problem.


Installing Nokogiri via Bundler on Mac (or why did this take two hours?)

If this post saves one person the headache of several hours of trying to build Nokogiri via Bundler on a Mac, maybe my time wasn’t wasted, but it was painful.

The setup…
Trying to install Nokogiri 1.6.1 as a dependency for other gems via Capistrano’s bundle:install task, I continually ran into “Failed to build gem native extension” error. Scrolling through the errors, the one item that stuck out was “You have to install development tools first.”

Although 100% certain my server had Xcode Command Line tools installed (it was recently updated at noted in the App Store), I reinstalled manually and tried to deploy again. Same error.

I then proceeded down the path of using Homebrew to install the various Nokogiri dependencies (e.g. libxml2, libxslt). Deploy…build…fail.

I ran “gem install nokogiri” locally on the server. Build…success. Tried to deploy again…build…fail.

Finally, I dug up the make log for Nokogiri (path below for reference) where I noted a message indicating that “gcc-4.2” was not installed. gcc is installed, but the build script seems specific. Not finding a switch to change the name of gcc, I went brute force:

sudo ln -s /usr/bin/gcc /usr/bin/gcc-4.2

Deploy…build…success! Annoying problem, solved.

Better suggestions welcome.

Make log: /shared/bundle/ruby/2.0.0/gems/nokogiri-1.6.1/ports/x86_64-apple-darwin13.1.0/ext/nokogiri/mkmf.log

Update
After all that, I noticed a warning: “Nokogiri was built against LibXML version 2.8.0, but has dynamically loaded 2.9.1”. After trying a few paths, I was able to rectify the warning via the steps in the comments of this :

  1. brew remove –force libxml2
  2. bundle config –delete build.nokogiri
  3. bundle exec gem uninstall nokogiri libxml-ruby
  4. bundle
  5. The commenter notes that Nokogiri 1.6+ now bundle the necessary libraries so there is no need to use the Homebrew versions.


Ransack: Search with Multiple Checkboxes (Rails)

I’ve been using the outstanding Ransack gem to enable search for a recent project. Ransack provides a tremendous amount of flexibility in a straightforward manner, but it took me a bit to understand how to search a single field across multiple values selected via checkboxes. My approach follows.

(Note that the field I was searching contained a serialized array of data, not to make life more difficult)

To start, a simplified model:

class Zoo < ActiveRecord::Base
  has_many :animals
end

class Animal < ActiveRecord::Base
  belongs_to :zoo # we'll assume an animal can only belong to one zoo
  validates_presence_of :name
end

Next, the controller, which is pretty much out-of-the-box from the Ransack documentation:

class ZoosController < ApplicationController
  def search # or index
    @search = Zoo.search(params[:q])
    @zoos = @search.result(distinct: true)
  end
end

And finally, the magic is really in the view:

<%= search_form_for @search, url: search_zoos_url do |f| %>
  <% Animal.all.uniq.each do |animal| %>
    # the check_box helper will not work as effectively here
    <%= check_box_tag('q[animals_name_cont_any][]', animal.name) %>
    <%= animal.name %>
  <% end %>
  <%= f.submit "Search" %>
<% end %>

The key is the name of the check box field. We are passing an array and also using Ransack’s cont_any predicate, which searches for any records whose name field contains one of the selected names.


WordPress.com Code Formatting…How Did I Not Know This!?

Somehow I have lived with pre blocks on this blog for much to long. On WordPress.com blogs (like this one), you can syntax-highlighted code very easily:

your code here

WordPress supports a wide variety of languages.

References


Sticky Navigation Bar with Skrollr

Parallax scrolling seems to be all the rage in web design these days.  It has a level of interactivity and richness that puts  the old click-and-wait experience to shame.  From simple and subtle (MMQB) to the complex (The Walking Dead), parallax can add a nice design flourish to most websites.  Of course, even simple effects are not free.

While redesigning a small business website, I wanted to add a few small touches to jazz up the minimal content, so I decided to add a spice of scrolling animations to the site.  In evaluating my options, I settled on Skrollr, which had the right mix of power and simplicity.  Skrollr is driven by CSS and HTML tag attributes, meaning there is little complex JavaScript for the end user, plus it works seamlessly across desktop and mobile.

Adding a stick navigation bar that drops in from the top of the screen using Skrollr was fairly straightforward, with two caveats that I will cover at the end of the article.

If you want to get to the end result: JSFiddle

First, our HTML markup before adding Skrollr:

<nav class="wrap">
  <div class="container">
    <div class="five columns">My Company</div>
    <div class="eleven columns last">
      <ul>
        <li><a href="#1">Item 1</a></li>
        <li><a href="#2">Item 2</a></li>
        <li><a href="#3">Item 3</a></li>
        <li><a href="#4">Item 4</a></li>
      </ul>
    </div>
  </div>
</nav>

Simple. Now, we can improve the style of the menu and also stick it to the top of the page via CSS. We’ll also add some transparency so it appears the page is passing under the menu as we scroll.

nav {
  background-color: rgba(255, 255, 255, 0.9);
  border: 1px solid red;
  height: 55px;
  top: 0;
  position: absolute; /* hold tight... */
  visibility: none;   /* we'll override these shortly */
  z-index: 1000;
}

/** some additional styling for navigation elements... **/

At this point, we should have a nice little navigation bar. It’s stuck at the top of the page and scrolls with the page though. Functionally, when the header is mostly off screen and then content is reaching the top of the viewport is when the navigation should slide in. Let’s modify our HTML to include Skrollr.

<nav class="wrap"
     data-anchor-target="#content"
     data-200-top="opacity:0;"
     data-150-top="visibility:visible; top: -55px; opacity: 0.3;"
     data-100-top="opacity: 1; position: fixed; top: 0;">
  <div class="container">
    <div class="five columns">My Company</div>
    <div class="eleven columns last">
      <ul>
        <li><a href="#1">Item 1</a></li>
        <li><a href="#2">Item 2</a></li>
        <li><a href="#3">Item 3</a></li>
        <li><a href="#4">Item 4</a></li>
      </ul>
    </div>
  </div>
</nav>

We’re doing a few things above:

  1. We use the data-anchor-target attribute and provided CSS selector to identify the page element on which the animation frames are triggered. Skrollr by default uses the tagged element, but can reference on the page via CSS.
  2. Animating the opacity, position, and visibility of the nav element. Skrollr handles the animation between the values, e.g. it “slides” the nav into place to animate the top position.
  3. Set the element as fixed on the page.

That’s it. As you can see in the JS Fiddle, this requires only minimal code and its fairly straightforward, except for two items:

Frame Positioning
Skrollr supports both absolute and relative positioning on the page, which is useful, though it took me a bit to wrap my head around it (and some trial-and-error). In this case, we are monitoring how close the content element is from the top of the viewport – as it gets closer, we animate in the nav (starting at 200 pixels from top and completing at 100 pixels). There is a nice graphic on the Skrollr website that helps in this regard, but depending on the animation/effect you wish to create, you may need to experiment:

Skrollr Positioning

Mobile Support
The Skrollr website has a great overview of how the library compensates for deferred processing of JavaScript in mobile browsers to fake scrolling. Because our example has both fixed and non-fixed elements on the page, we need to add a skrollr-body element that contains the scrollable content of our page (note in the Fiddle that the nav is not in this block). If you do not include the skrollr-body element, your page will not scroll properly, if at all.

This is just one example of adding a few small enhancements to a simple page, Skrollr can enable much, much more.

Complete Example

References


Rails Asset Pipeline + Bootstrap 3 Fonts

I admit it, I find the Rails Asset Pipeline confusing at times (as do seemingly many others judging from Stackoverflow and elsewhere).  Successfully adding the Bootstrap 3 glyphicon fonts took some trial-and-error amongst the various solutions I found as many still resulted in not found errors.

While there may be a better way, I found this approach most effective:

    1. Copy the contents of the Bootstrap “dist/fonts” directory to the “vendor/assets/fonts” directory (you will need to create a “fonts” directory.  Bootstrap’s minified JavaScript and CSS files can be copied to the appropriate directly in “vendor/assets” as well.
    2. Add the following to “config/application.rb” within the application config block:
      config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts')
      config.assets.precompile += %w(.svg .eot .woff .ttf)
    3. Utilizing SASS (or LESS) here is useful in order to leverage built-in asset pipeline helper methods.  In a common file used across your site, include the following:
      @font-face {
        font-family: 'Glyphicons Halflings';
        src: font-url('glyphicons-halflings-regular.eot');
        src: font-url('glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),
        font-url('glyphicons-halflings-regular.woff') format('woff'),
        font-url('glyphicons-halflings-regular.ttf') format('truetype'),
        font-url('glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');
      }

Thus far, Not Found errors seem to have been eliminated.  If there is a better way, please comment.


Very Useful

Rails Better Errors

Cleans-up Rails error messages, making them easier to understand and interactive. How have I missed this until now?


Yahoo News Digest

This post is something of a departure from my normal ramblings, but I didn’t want the release of Yahoo’s News Digest app to pass without note.  In a world of never-ending news feeds and infinite scrolling, returning to a fully consumable, information experience has been a joy over the past 24 hours.

News Digest delivers two daily digest, each with eight articles on the topics of the day — this morning focused on Chris Christie and Dennis Rodman.  The articles are short (more on that momentarily), reasonably informational, and contain links to other sources.  It’s a nice approach to mobile news in our increasingly attention-strained world.

As much as I’ve enjoyed News Digest in its first day of release, I do have a few quibbles:

  1. The articles are almost to short.  Most of the stories thus far leave me wanting for more.
  2. Proofread, please.  I’ve already noted a couple of simple grammatical errors that should be caught in such a short format.

http://itunes.apple.com/us/app/yahoo-news-atom/id784982356?ls=1&mt=8


Rails: Page Specific JavaScript with Asset Pipeline

After being away from Rails for several years, coming back to Rails 3/4 and its asset pipeline was a challenge at times.  While the performance gains and automation are quite valuable, the asset pipeline isn’t without its occasional challenges.  One of those challenges was the growing amount of JavaScript being executed on every page of our site.  While this mostly amounted to at worst errors in the console, it just felt icky (that’s a technical term).

Upon exploring Stack Overflow and various blog posts, I finally found a solution that felt somewhat better: Page-Specific Javascript using Coffeescript.  The overall solution was fairly clean, didn’t cause an explosion in the number of JS files, and also did not require an update to the config each time a new JS file was added.  For larger, more modular needs, other solutions (e.g. this one) may be more applicable, but this approach works fine for our medium size app.

I will not review the entire approach verbatim here, but I did make several changes to the aforementioned article.  It’s important to note that this solution utilizes the object-oriented nature of CoffeeScript to simplify life.

First, we will create a base class that houses the common code executed on every page.  I named this class base.js.coffee (in app/assets/javascripts).

window.MyApp ||= {}  # namespace for your app, replace as you desire
class MyApp.Base
  constructor:() ->
    # common code we want to run on every page
    console.log('I print on every page!')
    # be sure to return this
    this

Next, we can begin to build controller-specific classes on top of the base class.  Like Rails, we will use the convention of the naming the class the same as the accompanying controller.  For example, our CommentsController will be accompanied by a CoffeeScript class called MyApp.Comments in the file comments.js.coffee.

window.MyApp ||= {}
class MyApp.Comments extends MyApp.Base
  constructor:() ->
    super  # call Base class for core functionality
    this   # and be sure to return this

  # now, we enumerate the actions for which we want page-specific behavior
  index:() ->
    console.log('I only print on the comments#index page')
  show:() ->
    console.log('I only print on the comments#show page')
  edit:() ->
    # something special for the comments#edit page

Continue to build a CoffeeScript class for each of your controllers that require JavaScript beyond whatever your Base class takes responsibility for.  Be sure to include a method for each action/page on which unique functionality is required.

Finally, we need to bring everything together and ensure our code is called wherever necessary.  One approach would be to include the following in your application’s layout view, though it could also be included anywhere sure to be called.

<%= javascript_tag do %>
$(document).ready(function() {
  window.$M = new (MyApp.<%= params[:controller].capitalize %> || MyApp.Base)();
  if (typeof $M.<%= params[:action] %> === 'function') {
    return $M.<%= params[:action] %>.call();
  }
});
<% end %>

The above first instantiates a new instance of our controller’s accompanying class and then attempts to call the action method, if it exists.  The approach used in our app is slightly different, but this works as well.

Note that I did run into an issue using Turbolinks in conjunction with the above approach that we are yet to solve.  In short, despite using jquery.turbolinks and other known approaches, the action methods were being called multiples times per page.  I have seen mention of this behavior when Turbolinks is used in conjunction with anonymous functions (e.g. those created by CoffeeScript), but have not found a fix.  Please comment if you can help.